/*
 *
 *  Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
 *  SPDX-License-Identifier: Apache-2.0
 *
 */
import React, { Ref, useCallback, useContext, useEffect, useImperativeHandle, useState, useRef } from 'react';
import { Card, Checkbox, Form, H3, Justify, Layout, Select, ExternalLink, Button, Modal, Input } from 'tea-component';
import { Control, Controller, useForm } from 'react-hook-form';
import formUtils, { Validator } from '../../utils/form-utils';
import {
  useFetchAuthOrgList,
  useFetchAuthRoleList,
  useFetchChainAuthList,
  useFetchChainAuthModify,
} from '../../common/apis/chains/hooks';
import { ChainDetailContext } from './chain-detail';
import { Chain, ChainAuth as ChainAuthType } from '../../common/apis/chains/interface';
import { UseFormSetValue, UseFormGetValues } from 'react-hook-form/dist/types/form';
import { CheckChangeContext } from 'tea-component/lib/check/Check';
const { getStatus } = formUtils;
const { Content } = Layout;
const { TextArea } = Input;
export const AuthRoleMap = {
  0: 'Admin',
  1: 'Client',
};

/**
 * 权限配置类型
 */
export const ChainAuthTypes: {
  [key: number]: {
    value: string;
    title: string;
  };
} = {
  0: {
    title: '增加新节点',
    value: 'NODE_ADDR_UPDATE',
  },
  1: {
    title: '更新信任根CA证书',
    value: 'TRUST_ROOT_UPDATE',
  },
  2: {
    title: '踢出共识节点',
    value: 'CONSENSUS_EXT_DELETE',
  },
  3: {
    title: '更新区块配置',
    value: 'BLOCK_UPDATE',
  },
  4: {
    title: '部署合约',
    value: 'INIT_CONTRACT',
  },
  5: {
    title: '升级合约',
    value: 'UPGRADE_CONTRACT',
  },
  6: {
    title: '冻结合约',
    value: 'FREEZE_CONTRACT',
  },
  7: {
    title: '解冻合约',
    value: 'UNFREEZE_CONTRACT',
  },
  8: {
    title: '废止合约',
    value: 'REVOKE_CONTRACT',
  },
  9: {
    title: '修改链权限',
    value: 'PERMISSION_UPDATE',
  },
  11: {
    title: '增加新共识组织节点',
    value: 'NODE_ORG_ADD',
  },
  12: {
    title: '删除新共识组织节点',
    value: 'NODE_ORG_DELETE',
  },
  13: {
    title: '增加共识节点',
    value: 'NODE_ID_ADD',
  },
  14: {
    title: '删除共识节点',
    value: 'NODE_ID_DELETE',
  },
  15: {
    title: '新增组织',
    value: 'TRUST_ROOT_ADD',
  },
  16: {
    title: '删除组织',
    value: 'TRUST_ROOT_DELETE',
  },
};

// 公钥投票事件
export const PublicChainAuthTypes: {
  [key: number]: {
    value: string;
    title: string;
  };
} = {
  3: {
    title: '修改链配置',
    value: 'BLOCK_UPDATE',
  },
  4: {
    title: '部署合约',
    value: 'INIT_CONTRACT',
  },
  5: {
    title: '升级合约',
    value: 'UPGRADE_CONTRACT',
  },
  6: {
    title: '冻结合约',
    value: 'FREEZE_CONTRACT',
  },
  7: {
    title: '解冻合约',
    value: 'UNFREEZE_CONTRACT',
  },
  8: {
    title: '废止合约',
    value: 'REVOKE_CONTRACT',
  },
};

/**
 * 投票规则
 */
export const VOTE_RULE_MAP: {
  [key: number]: {
    title: string;
    value: string;
  };
} = {
  0: {
    title: 'Majority',
    value: 'MAJORITY',
  },
  1: {
    title: 'ANY',
    value: 'ANY',
  },
  3: {
    title: 'ALL',
    value: 'ALL',
  },
  // 4: { // 本期先不上
  //   title: 'Forbidden',
  //   value: 'FORBIDDEN',
  // },
};

export default function ChainAuth() {
  const { chainId } = useContext(ChainDetailContext);
  const { run: fetchChainAuthList, data: authTypes } = useFetchChainAuthList();
  const chainAuthModal = useRef<any>();
  useEffect(() => {
    chainId && fetchChainAuthList(chainId);
  }, []);
  console.log('----authTypes', authTypes);
  return (
    <Content>
      <Content.Header title="区块链管理/区块链概览/链管理权限配置" />
      <Content.Body full>
        <Card>
          <Card.Body>
            <Justify
              className={'auth-top-tip'}
              left={
                <H3>
                  此处默认展示常用的一些链账户权限，和投票策略，如需管理更多权限，可点击修改更多权限按钮。如想知道信安链一共有哪些权限，可查看开源文档
                  <ExternalLink
                    href={
                      'https://docs.chainmaker.org.cn/tech/%E8%BA%AB%E4%BB%BD%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86.html#id9'
                    }
                  >
                    身份权限管理模块
                  </ExternalLink>
                  。
                </H3>
              }
              right={
                <Button
                  type={'primary'}
                  onClick={() => {
                    chainAuthModal.current.show();
                  }}
                >
                  修改更多权限
                </Button>
              }
            />
          </Card.Body>
        </Card>
        {authTypes.map((item) => (
          <ChainAuthCard
            key={item.Type}
            isAllSelected={item.OrgType}
            title={
              ChainAuthTypes[item.Type]
                ? `${ChainAuthTypes[item.Type].title}(${ChainAuthTypes[item.Type].value})`
                : item.AuthName
            }
            chainId={chainId as string}
            auth={item}
          />
        ))}
        <ChainAuthModal ref={chainAuthModal} />
      </Content.Body>
    </Content>
  );
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function ChainAuthCardContainer(
  props: { title: string; chainId: string; auth: ChainAuthType; isAllSelected?: number },
  parentRef: Ref<any>,
) {
  const {
    control,
    getValues,
    setValue,
    formState: { isValidating, isSubmitted },
  } = useForm({ mode: 'onChange' });
  const { run: modifyAuth } = useFetchChainAuthModify();
  const handleSubmit = useCallback(() => {
    const { Rule, OrgList, RoleList, Reason } = getValues();
    if (!OrgList.length || !RoleList.length) {
      return;
    }

    modifyAuth({
      ...(!/.*[\u4e00-\u9fa5]+.*$/.test(props.title) && {
        AuthName: props.title,
      }),
      Reason: Reason || '',
      Type: props.auth.Type,
      Rule: Number(Rule),
      ChainId: props.chainId,
      // PercentNum: getValues('PercentNum'),
      OrgList: OrgList.includes('__all_')
        ? []
        : OrgList.filter((val: string) => val).map((item: string) => ({
            OrgId: item,
          })),
      RoleList: RoleList.includes('__all_')
        ? []
        : RoleList.map((item: string) => ({
            Role: +item,
          })),
    });
  }, []);

  useImperativeHandle(parentRef, () => ({}));

  return (
    <Card>
      <Card.Body
        title={
          <Justify
            left={<H3>{props.title}</H3>}
            right={
              <Button
                onClick={() => {
                  const { destroy } = Modal.show({
                    onClose: () => destroy(),
                    caption: '修改链权限投票策略',
                    children: (
                      <>
                        <Modal.Body>
                          {reasonFormItem(control, '修改该权限的投票策略需要其他组织投票同意，请输入修改理由。', {
                            display: 'block',
                          })}
                        </Modal.Body>
                        <Modal.Footer>
                          <Button
                            type="primary"
                            onClick={() => {
                              handleSubmit();
                              destroy();
                              setValue('Reason', '');
                            }}
                          >
                            确认
                          </Button>
                          <Button
                            onClick={() => {
                              destroy();
                              setValue('Reason', '');
                            }}
                          >
                            关闭
                          </Button>
                        </Modal.Footer>
                      </>
                    ),
                  });
                }}
              >
                确认修改
              </Button>
            }
          />
        }
      >
        <Form>
          <ChainAuthForm
            isAllSelected={props.isAllSelected}
            getValues={getValues}
            isDefaultAuth
            setValue={setValue}
            auth={props.auth}
            chainId={props.chainId}
            control={control}
            isSubmitted={isSubmitted}
            isValidating={isValidating}
          />
        </Form>
      </Card.Body>
    </Card>
  );
}

/**
 * 参与组织全选
 */
const select_all_org = {
  OrgName: '全选',
  OrgId: '__all_',
};

function ChainAuthForm({
  getValues,
  control,
  auth,
  chainId,
  isValidating,
  isSubmitted,
  isDefaultAuth,
  setValue,
  isAllSelected,
}: {
  control: Control;
  getValues: UseFormGetValues<any>;
  setValue: UseFormSetValue<any>;
  auth: ChainAuthType | undefined;
  chainId: Chain['ChainId'];
  isValidating: boolean;
  isSubmitted: boolean;
  /**
   * 是否是默认权限，默认权限需要请求后台拿到缺省选中值
   */
  isDefaultAuth: boolean;
  isAllSelected?: number; // 是否全选
}) {
  const { orgs, run: fetchOrgList } = useFetchAuthOrgList();
  const { data: roles, run: fetchAuthRoleList } = useFetchAuthRoleList();
  const [isChangeOrg, setIsChangeOrg] = useState<boolean>(false);
  const onOrgSelectChange = useCallback(
    (value: string[], context: CheckChangeContext) => {
      setIsChangeOrg(true);
      if (context.check.name === select_all_org.OrgId && context.check.value) {
        setValue('OrgList', [select_all_org.OrgId, ...orgs.map((item) => item.OrgId)]);
      } else if (context.check.name !== select_all_org.OrgId && !context.check.value) {
        setValue(
          'OrgList',
          value.filter((item) => item !== select_all_org.OrgId),
        );
      } else {
        setValue('OrgList', value);
      }
    },
    [orgs],
  );

  useEffect(() => {
    if (auth) {
      fetchOrgList(chainId, isDefaultAuth ? auth.Type : undefined, auth.AuthName);
      fetchAuthRoleList({ ChainId: chainId, Type: isDefaultAuth ? auth.Type : undefined, AuthName: auth.AuthName });
    }
  }, [auth, isDefaultAuth]);

  return (
    <>
      {auth && Boolean(roles.length) && Boolean(orgs?.length) && (
        <>
          <Controller
            control={control}
            rules={{
              validate: () => undefined,
              required: true,
            }}
            name="Rule"
            defaultValue={String(auth!.PolicyType)}
            render={({ field, fieldState }) => (
              <Form.Item
                label="投票规则"
                required
                status={getStatus({
                  fieldState,
                  isValidating,
                  isSubmitted,
                })}
              >
                <Select
                  placeholder={'请选择投票规则'}
                  options={Object.entries(VOTE_RULE_MAP).map((arr) => ({
                    text: arr[1].title,
                    value: String(arr[0]),
                  }))}
                  {...field}
                />
              </Form.Item>
            )}
          />
          <Controller
            control={control}
            rules={{
              required: true,
              validate: () => undefined,
            }}
            defaultValue={(orgs || [])
              .filter((item) => item.Selected)
              .map((item) => item.OrgId)
              .concat(isAllSelected ? '__all_' : '')}
            name="OrgList"
            render={({ field }) => (
              <Form.Item
                status={getValues('OrgList')?.length === 0 && isChangeOrg ? 'error' : undefined}
                required
                label="参与组织"
                message={getValues('OrgList')?.length === 0 && isChangeOrg ? '参与组织不能为空' : ''}
              >
                <Checkbox.Group {...field} onChange={onOrgSelectChange}>
                  {[select_all_org, ...(orgs || [])].map((item) => (
                    <Checkbox key={item.OrgId} name={item.OrgId}>
                      {item.OrgName}
                    </Checkbox>
                  ))}
                </Checkbox.Group>
              </Form.Item>
            )}
          />
          <Controller
            control={control}
            name="RoleList"
            rules={{
              required: true,
              validate: () => undefined,
            }}
            defaultValue={roles.filter((item) => item.Selected).map((item) => String(item.Role))}
            render={({ field, fieldState }) => (
              <Form.Item
                required
                status={getStatus({
                  fieldState,
                  isValidating,
                  isSubmitted,
                })}
                label="参与角色"
              >
                <Checkbox.Group {...field}>
                  {roles.map((item) => (
                    <Checkbox key={item.Role} name={String(item.Role)}>
                      {AuthRoleMap[item.Role]}
                    </Checkbox>
                  ))}
                </Checkbox.Group>
              </Form.Item>
            )}
          />
        </>
      )}
    </>
  );
}

const ChainAuthCard = React.forwardRef(ChainAuthCardContainer);

/**
 * 用户自定义权限
 */
const custom_auth = {
  Type: 9,
  PolicyType: 0,
  AuthName: '',
  OrgType: 0,
};

function ChainAuthModalContainer({}, ref: any) {
  const [visible, setVisible] = useState(false);
  const { chainId } = useContext(ChainDetailContext);
  const {
    setValue,
    control,
    getValues,
    reset,
    formState: { isValidating, isSubmitted },
  } = useForm({ mode: 'all' });
  const { run: modifyAuth } = useFetchChainAuthModify();

  const close = useCallback(() => {
    setVisible(false);
    reset();
  }, []);

  const [isValid, setIsValid] = useState<boolean>(false);

  useEffect(() => {
    // eslint-disable-next-line @typescript-eslint/naming-convention
    const { AuthName, OrgList, RoleList } = getValues();
    setIsValid(AuthName && OrgList.length > 0 && RoleList.length > 0);
  }, [getValues()]);

  const handleSave = useCallback(() => {
    // eslint-disable-next-line @typescript-eslint/naming-convention
    const { AuthName, Rule, OrgList, RoleList, Reason } = getValues();
    if (!OrgList.length || !RoleList.length) {
      return;
    }
    modifyAuth({
      Reason: Reason || '',
      AuthName,
      Rule: +Rule,
      Type: -1,
      ChainId: chainId as string,
      OrgList: OrgList.includes('__all_')
        ? []
        : OrgList.filter((val: string) => val).map((item: string) => ({
            OrgId: item,
          })),
      RoleList: RoleList.includes('__all_')
        ? []
        : RoleList.map((item: string) => ({
            Role: +item,
          })),
    });
    close();
  }, []);

  useImperativeHandle(ref, () => ({
    show: () => setVisible(true),
  }));

  return (
    <Modal caption="修改更多权限" visible={visible} onClose={close}>
      <Modal.Body>
        <Form>
          <Controller
            render={({ field, fieldState }) => (
              <Form.Item
                label={'权限资源名称'}
                required
                status={getStatus({ fieldState, isSubmitted, isValidating })}
                message={fieldState.error?.message}
              >
                <Input placeholder="请输入权限资源名" {...field} />
              </Form.Item>
            )}
            name="AuthName"
            control={control}
            rules={{
              validate: (AuthName) => Validator.AuthName(AuthName),
            }}
          />
          <ChainAuthForm
            getValues={getValues}
            setValue={setValue}
            control={control}
            auth={custom_auth}
            chainId={chainId as string}
            isValidating={isValidating}
            isDefaultAuth={true}
            isSubmitted={isSubmitted}
          />
          {reasonFormItem(control, '修改理由')}
        </Form>
      </Modal.Body>
      <Modal.Footer>
        <Button type="primary" disabled={!isValid} onClick={handleSave}>
          确定
        </Button>
        <Button onClick={close}>取消</Button>
      </Modal.Footer>
    </Modal>
  );
}

const ChainAuthModal = React.forwardRef(ChainAuthModalContainer);

// 修改理由
function reasonFormItem(control: Control, label: string, style?: React.CSSProperties) {
  return (
    <Controller
      control={control}
      name="Reason"
      render={({ field }) => (
        <Form.Item label={label} style={style || {}}>
          <TextArea className="tea-mt-3n" size="full" {...field} placeholder="请输入修改理由（选填）" />
        </Form.Item>
      )}
    />
  );
}
